﻿using System;
using System.Drawing;
using Microsoft.WindowsCE.Forms;
using System.Windows.Forms;

namespace Spencen.Mobile.UI
{
    public static class DrawingSupport
    {
        /// <summary>
        /// Determines whether the specified point lies within the area bounded by the specified vertices.
        /// </summary>
        /// <param name="vertices">The points that define the polygon.</param>
        /// <param name="point">The point to check.</param>
        /// <returns><see langword="true"/> if the <paramref name="point"/> lies within the area bounded 
        /// by the <paramref name="vertices"/>, <see langword="false"/> otherwise.</returns>
        public static bool PolygonContains( PointF[] vertices, PointF point )
        {
            if ( vertices == null )
                throw new ArgumentNullException( "vertices" );

            bool inside = false;
            for ( int i = 0, j = vertices.Length - 1; i < vertices.Length; j = i++ )
            {
                if ( ( ( ( vertices[ i ].Y <= point.Y ) && ( point.Y < vertices[ j ].Y ) ) ||
                    ( ( vertices[ j ].Y <= point.Y ) && ( point.Y < vertices[ i ].Y ) ) ) &&
                    ( point.X < ( vertices[ j ].X - vertices[ i ].X ) * ( point.Y - vertices[ i ].Y ) / ( vertices[ j ].Y - vertices[ i ].Y ) + vertices[ i ].X ) )
                    inside = !inside;
            }

            return inside;
        }

        /// <summary>
        /// Determines whether the specified point lies within the area bounded by the specified vertices.
        /// </summary>
        /// <param name="vertices">The points that define the polygon.</param>
        /// <param name="point">The point to check.</param>
        /// <returns><see langword="true"/> if the <paramref name="point"/> lies within the area bounded 
        /// by the <paramref name="vertices"/>, <see langword="false"/> otherwise.</returns>
        public static bool PolygonContains( Point[] vertices, Point point )
        {
            if ( vertices == null )
                throw new ArgumentNullException( "vertices" );

            bool inside = false;
            for ( int i = 0, j = vertices.Length - 1; i < vertices.Length; j = i++ )
            {
                if ( ( ( ( vertices[ i ].Y <= point.Y ) && ( point.Y < vertices[ j ].Y ) ) ||
                    ( ( vertices[ j ].Y <= point.Y ) && ( point.Y < vertices[ i ].Y ) ) ) &&
                    ( point.X < ( vertices[ j ].X - vertices[ i ].X ) * ( point.Y - vertices[ i ].Y ) / ( vertices[ j ].Y - vertices[ i ].Y ) + vertices[ i ].X ) )
                    inside = !inside;
            }

            return inside;
        }

        public static float DistanceBetweenPoints( Point point1, Point point2 )
        {
            return (float)Math.Sqrt( Math.Pow( point1.X - point2.X, 2 ) + Math.Pow( point1.Y - point2.Y, 2 ) );
        }

        public static float AngleBetweenPoints( Point point1, Point point2 )
        {
            float dx = point2.X - point1.X;
            float dy = point2.Y - point1.Y;
            double angle = RadToDeg( Math.Atan( dy / dx ) );
            if ( dx < 0 )
                angle += 180;

            return (float)angle;
        }

        public static double RadToDeg( double rad )
        {
            return rad / Math.PI * 180;
        }

        public static double DegToRad( double deg )
        {
            return deg / 180.0f * Math.PI;
        }

        // http://msdn.microsoft.com/en-us/library/ms404359.aspx
        // Method to create a rotated font using a LOGFONT structure.
        public static Font CreateRotatedFont( Graphics g, string fontname, float emSize, int angleInDegrees )
        {
            var logf = new LogFont();

            // Create graphics object for the form, and obtain
            // the current DPI value at design time. In this case,
            // only the vertical resolution is petinent, so the DpiY
            // property is used. 

            // Scale an 18-point font for current screen vertical DPI.
            logf.Height = (int)( -emSize * 1.37 * g.DpiY / 96 );

            // Convert specified rotation angle to tenths of degrees.  
            logf.Escapement = angleInDegrees * 10;

            // Orientation is the same as Escapement in mobile platforms.
            logf.Orientation = logf.Escapement;

            logf.FaceName = fontname;
            //logf.Weight = LogFontWeight.Bold;

            // Set LogFont enumerations.
            logf.CharSet = LogFontCharSet.Default;
            logf.OutPrecision = LogFontPrecision.Default;
            logf.ClipPrecision = LogFontClipPrecision.Default;
            logf.Quality = LogFontQuality.ClearType;
            logf.PitchAndFamily = LogFontPitchAndFamily.Default;

            return Font.FromLogFont( logf );
        }

        public static Dpi GetDpi( Graphics graphics )
        {
            return new Dpi( (int) graphics.DpiX, (int) graphics.DpiY );
        }

        public static Dpi GetDpi( Control control )
        {
            using ( var graphics = control.CreateGraphics() )
                return new Dpi( (int) graphics.DpiX, (int) graphics.DpiY );
        }
    }
}
